﻿using System;
using System.Globalization;
using System.Linq;
using HighDiveEngine.Aggregates;
using HighDiveEngine.Resources;

namespace HighDiveEngine.Model
{
    /// <summary>
    /// Dataclass that holds data for a dive. Difficulty i automatically calculated inside the constructor
    /// </summary>
    public class Dive : IEquatable<Dive>
    {
        private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
        
        #region Properties
        /// <summary>
        /// DatabasId
        /// </summary>
        public int? DbId { get; set; }
        public Diver Diver { get; set; }
        public string DiveCode { get; set; }
        public double? Difficulty { get; set; }
        public int DiveNumber { get; set; }
        public int? QueueOrderNumber { get; set; }
        public int? DiveHeight { get; set; }
        public string Date { get; set; }
        public DiveScoreList DiveScoreList { get; set; }
        public double? TotalScore { get; set; }

        #endregion

        #region Public Methods

        public void CalculateDifficulty()
        {
            if (DiveCode != null && DiveHeight != null)
            {
                Difficulty = DiveCodeDifficultyCalculator.Instance.GetDifficulty(DiveCode, DiveHeight);
            }
            else
            {
                Log.Error("DiveCode = " + DiveCode + " DiveHeight = " + DiveHeight);
                throw new DiveCodeException("DiveCode and DiveHeight cannot be null!");
            }
        }

        /// <summary>
        /// Calculates the total score of a dive with a full judge score.
        /// </summary>
        public void CalculateTotalScore()
        {
            TotalScore = (DiveScoreList.Sum() - DiveScoreList.Max() - DiveScoreList.Min()) / (DiveScoreList.Count() - 2);
            TotalScore *= 3 * Difficulty;

            if (Log.IsInfoEnabled)
            {
                Log.Info("Dive " + QueueOrderNumber + " (DbId:" + DbId + ") totalscore updated to " + TotalScore); 
            }
        }


        public override string ToString()
        {
            string diveString = Diver.FirstName + " " + Diver.LastName + " | Start Number: " + Diver.StartNumber + " | Dive: " +
                                DiveNumber + " | " + DiveCode + " | Height: " + DiveHeight + "m | DD: " + Convert.ToDouble(Difficulty).ToString(CultureInfo.InvariantCulture);
            if (DiveScoreList.Count > 0)
            {
                diveString += " | Score: ";
                diveString += DiveScoreList[0].Score.ToString(CultureInfo.InvariantCulture);
                for (int i = 1; i < DiveScoreList.Count; i++)
                {
                    diveString += " | " + DiveScoreList[i].Score.ToString(CultureInfo.InvariantCulture);
                }
            }
            if (TotalScore != null)
                diveString += " | Total: " + Convert.ToDouble(TotalScore).ToString(CultureInfo.InvariantCulture);
            if(Date != null)
                if (Date.Length > 0)
                    diveString += " | " + Date.Substring(11, 4).Insert(2, ":");
            return diveString;
        }

        #endregion

        #region Constructors

        /// <summary>Creates a new Dive</summary>
        public Dive()
        {
            DbId = null;
            Diver = null;
            DiveCode = null;
            Difficulty = null;
            DiveNumber = 0;
            QueueOrderNumber = null;
            DiveHeight = null;
            DiveScoreList = new DiveScoreList();
            TotalScore = null;
            Date = null;
        }

        #endregion

        #region IEquatable
        public bool Equals(Dive other)
        {
            if (other == null) return false;

            return Diver.IdNumber == other.Diver.IdNumber && Diver.StartNumber == other.Diver.StartNumber && DiveNumber == other.DiveNumber;
        }

        #endregion
    }
}
